#include<iostream>
#include <memory>
using namespace std;


class A
{
public:
    A() { cout << "A()" << endl; }
    ~A() { cout << "~A()" << endl; }
};

// template<class T>
// class smartPtr
// {
//     T* _p;
// public:
//     smartPtr(T* p)
//         :_p(p)
//     {}
//     ~smartPtr()
//     {
//         cout << "~smartPtr()" << endl;
//         delete _p;
//     }
//     T& operator* () { return *_p; }
//     T* operator-> () { return _p; }
// };

void test01()
{
    try{
        shared_ptr<A> arr(new A[10]);
        int x, y;
        cout << "请输入被除数与除数" << endl;
        cin >> x >> y;	// 输入 1 0
        if(y == 0)
            throw "被除数为0!";
        else
            cout << x / y << endl;
    }
    catch(const char* err_message)
    {
        cout << err_message << endl;
    }
}

struct DeleteA
{
    void operator()(A p[])
    {
        delete[] p;
    }
};
void test02()
{
    // shared_ptr<A> p1(new A); 
    auto p1 = make_shared<A>();
    // shared_ptr<A> p2(new A[5], [](A* p) { delete[] p; });   // 指向数组需要手写删除器
    // shared_ptr<A[]> p2(new A[5]);   // C++17支持

    // unique_ptr<A> p3(new A);
    // // unique_ptr<A[]> p4(new A[5]);   // 指向数组的写法
    // unique_ptr<A[], DeleteA> p4(new A[2]);  // 或者手写删除器
    // // unique_ptr<A[], ([](A* p){ delete[] p; })> p4(new A[2]);  // 不可用lambda
}

int main()
{
    // A* a = new A[10];
    // delete[] a;
    test02();
    return 0;
}

// class A
// {};

// class B : public A
// {};

// void test01()
// {
//     try{
//         int x, y;
//         cout << "请输入被除数与除数" << endl;
//         cin >> x >> y;	// 输入 1 0
//         if(y == 0)
//             throw "除数为0!";     // 抛出int类型
//         else
//             cout << x / y << endl;
//     }
//     catch(const string& err_message)    // 该catch块用size_t类型接收
//     {
//         cout << "test01(): catch(size_t err_message)" << endl;
//     }
// }

// void test01()
// {
//     try{
//         int x, y;
//         cout << "请输入被除数与除数" << endl;
//         cin >> x >> y;	// 输入 1 0
//         if(y == 0)
//             throw string("除数为0!");     // 抛出const char*类型的异常
//         else
//             cout << x / y << endl;
//     }
//     catch(const string& err_message)    // 该catch块接收string类型
//     {
//         cout << "test01(): catch(const string& err_message)" << endl;
//         throw;  // 重新抛出异常
//     }
// }

// void func() noexcept
// {
//     // ... 
//     if(0)
//         throw "违反了承诺";
// }
// int main()
// {
//     try{
//         func();
//     }
//     catch(...)
//     {
//         cout << "main(): catch(...)" << endl;
//     }
//     return 0;
// }

#if 0
int Div(int a, int b)
{
    if(b == 0) 
    {
        // throw "Divisor is 0";   // 这里不会匹配string
        string s("Divisor is 0");
        throw s; // 这里会拷贝一份临时对象，再抛出去
    }
    else
        return a / b;
}

void test()
{
    try{
        int x, y;
        cin >> x >> y;
        Div(x, y);  // 这里throw了const char* 类型的异常，但是没有匹配的catch，会去上一层找匹配的
        // 严格匹配，不会隐式类型转换。但有例外：可以抛出派生类对象，用基类捕获
        cout << "xxxxx" << endl;
    }
    catch(string s)
    {
        cout << s << endl;
    }
}

int main()
{
    try{
        test();
    }
    catch(const char* s)    // 在这里找到了
    {
        cout << s << endl;
    }
    catch(...)  // 表示可以捕获任何类型的异常
    {
        cout << "unknow error" << endl;
    }
    return 0;
}
#endif

// class Exception
// {
// public:
//     Exception(const string& errmsg, int id)
//         :_errmsg(errmsg)
//         ,_id(id)
//     {}
//     virtual string what() const 
//     {
//         return _errmsg;
//     } 
// protected:
//     string _errmsg; 
//     int _id;
// };

// #include<chrono> 有关时间的库


// int Div(int a, int b) noexcept
// {
//     if(b == 0) 
//     {
//         string s("Divisor is 0");
//         throw s; // 这里会拷贝一份临时对象，再抛出去
//     }
//     else
//         return a / b;
// }

// void test()
// {
//     int* arr = new int[10];
//     try{
//         int x, y;
//         cin >> x >> y;
//         Div(x, y);  // 这里如果抛异常，那就会存在内存泄漏
//         cout << "xxxxx" << endl;
//     }
//     catch(...)
//     {
//         delete[] arr;
//         throw;  // 无法处理该异常，重新抛出，交给上层处理
//     }
//     delete[] arr;
// }

// // void func() noexcept; // 表示该函数不会抛异常
// int main()
// {
//     try{
//         test();
//     }
//     catch(const char* s)    // 在这里找到了
//     {
//         cout << s << endl;
//     }
//     catch(...)  // 表示可以捕获任何类型的异常
//     {
//         cout << "unknow error" << endl;
//     }
//     return 0;
// }
